package com.syyo.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.syyo.admin.domain.entity.MenuEntity;
import com.syyo.admin.domain.entity.RoleEntity;
import com.syyo.admin.domain.export.RoleExport;
import com.syyo.admin.domain.req.RoleReq;
import com.syyo.admin.domain.resp.RoleResp;
import com.syyo.admin.mapper.RoleDeptMapper;
import com.syyo.admin.mapper.RoleMapper;
import com.syyo.admin.mapper.RoleMenuMapper;
import com.syyo.admin.mapper.UserRoleMapper;
import com.syyo.admin.service.RoleService;
import com.syyo.common.enums.ResultEnum;
import com.syyo.common.exception.SysException;
import com.syyo.common.utils.MyFileUtil;
import com.syyo.common.utils.MyListUtils;
import com.syyo.common.utils.MyStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wang
 * @since 2020-07-17
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleEntity> implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private RoleDeptMapper roleDeptMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    @Transactional
    public int add(RoleReq req) {
        RoleEntity entity = new RoleEntity();
        BeanUtils.copyProperties(req, entity);
        LocalDateTime now = LocalDateTime.now();
        entity.setUpdateTime(now);
        entity.setCreateTime(now);
        int insert = roleMapper.insert(entity);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80011.getCode(), ResultEnum.E_80011.getMessage());
        }

        List<Integer> deptList = req.getDeptList();
        if (req.getDataScope() == 2 && MyListUtils.isNotEmpty(deptList)) {
            roleDeptMapper.addAll(entity.getRoleId(), deptList);
        }
        return insert;

    }

    @Override
    @Transactional
    public int del(RoleReq req) {
        List<Integer> ids = req.getIds();
        // admin角色不能删除
        if (ids.contains(1)) {
            throw new SysException(ResultEnum.E_90007.getCode(), ResultEnum.E_90007.getMessage());
        }

        int count = userRoleMapper.findInRoleId(ids);
        if (count > 0) {
            throw new SysException(ResultEnum.E_70001.getCode(), ResultEnum.E_70001.getMessage());
        }
        // 删除关联的角色部门中间表
        for (Integer id : ids) {
            roleDeptMapper.del(id);
        }

        boolean b = removeByIds(ids);
        if (!b) {
            throw new SysException(ResultEnum.E_80012.getCode(), ResultEnum.E_80012.getMessage());
        }
        return 1;
    }

    @Override
    @Transactional
    public int edit(RoleReq req) {
        Integer roleId = req.getRoleId();
        RoleEntity entity = new RoleEntity();
        BeanUtils.copyProperties(req, entity);
        LocalDateTime now = LocalDateTime.now();
        entity.setUpdateTime(now);
        int insert = roleMapper.updateById(entity);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80013.getCode(), ResultEnum.E_80013.getMessage());
        }

        // 选择数据范围前，先删除角色关联的部门
        roleDeptMapper.del(roleId);
        List<Integer> deptList = req.getDeptList();
        if (req.getDataScope() == 2 && MyListUtils.isNotEmpty(deptList)) {
            // 添加新的角色关联部门
            Integer count = roleDeptMapper.addAll(roleId, deptList);
            if (count != deptList.size()) {
                throw new SysException(ResultEnum.E_80013.getCode(), ResultEnum.E_80013.getMessage());
            }
        }
        return insert;
    }

    @Override
    public RoleResp findOne(Integer id) {
        RoleEntity entity = roleMapper.selectById(id);

        // 查询对应的菜单
        List<Integer> list = roleMenuMapper.getMenuId(id);
        RoleResp roleResp = new RoleResp();
        BeanUtils.copyProperties(entity, roleResp);
        roleResp.setMenuIdList(list);
        if (entity.getDataScope() == 2) {
            List<Integer> deptIdList = roleDeptMapper.getDeptById(id);
            roleResp.setDeptIdList(deptIdList);
        }
        return roleResp;
    }

    @Override
    public IPage<RoleEntity> findAll(Integer pageNum, Integer pageSize, RoleReq req) {
        Page<RoleEntity> teacherPage = new Page<RoleEntity>(pageNum, pageSize);
        QueryWrapper<RoleEntity> wrapper = new QueryWrapper<>();
        String roleName = req.getRoleName();
        //判断条件值是否为空，如果不为空拼接条件
        if (MyStringUtils.isNotEmpty(roleName)) {
            //构建条件
            wrapper.like("role_name", roleName);
        }
        if (MyStringUtils.isNotEmpty(req.getStartDate())) {
            //构建条件
            wrapper.between("create_time", req.getStartDate(), req.getEndDate());
        }
        return roleMapper.selectPage(teacherPage, wrapper);
    }

    @Override
    public Collection<GrantedAuthority> findByUsersId(Integer userId) {
        Set<RoleEntity> roles = roleMapper.findByUsersId(userId);

        //添加角色标识
        Set<String> permissions = roles.stream().filter(role -> MyStringUtils.isNotEmpty(role.getRoleKey())).map(RoleEntity::getRoleKey).collect(Collectors.toSet());
        //添加菜单的权限标识
        permissions.addAll(
                roles.stream().flatMap(role -> role.getMenus().stream())
                        .filter(menu -> MyStringUtils.isNotEmpty(menu.getPerms()))
                        .map(MenuEntity::getPerms).collect(Collectors.toSet())
        );
        return permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public int auth(RoleReq req) {
        //校验角色id是否存在
        Integer roleId = req.getRoleId();
        RoleEntity sysRole = roleMapper.selectById(roleId);
        if (sysRole == null) {
            throw new SysException(ResultEnum.E_80015.getCode(), ResultEnum.E_80015.getMessage());
        }
        //添加角色菜单中间表
        List<Integer> menuIdList = req.getMenuIdList();
        if (MyListUtils.isNotEmpty(menuIdList)) {
            //删除该角色在中间表的权限信息
            roleMenuMapper.del(roleId);

            Integer add = roleMenuMapper.addAll(roleId, menuIdList);
            if (add != menuIdList.size()) {
                throw new SysException(ResultEnum.E_80011.getCode(), ResultEnum.E_80011.getMessage());
            }
        }
        return menuIdList.size();


    }

    @Override
    public void export(RoleExport export, HttpServletResponse response) {
        List<RoleEntity> sysRoles = roleMapper.selectList(null);
        List<RoleExport> list = new ArrayList<>();
        for (RoleEntity sysUser : sysRoles) {
            RoleExport export2 = new RoleExport();
            BeanUtils.copyProperties(sysUser, export2);
            list.add(export2);
        }
        // 导出文件
        MyFileUtil.exportFile(response, "user_", list, RoleExport.class);
    }
}
